
package com.hmsproject.db.expediadb;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;

import com.hmsproject.datastructures.HotelImage;
import com.hmsproject.datastructures.Hotel;
import com.hmsproject.datastructures.StarValue;
import com.hmsproject.datastructures.comparators.HotelDistanceComparatorDescending;
import com.hmsproject.datastructures.comparators.HotelNameComparatorAscending;
import com.hmsproject.datastructures.comparators.HotelPopularityComparatorDescending;
import com.hmsproject.datastructures.comparators.HotelPriceComparatorAscending;
import com.hmsproject.datastructures.comparators.HotelPriceComparatorDescending;
import com.hmsproject.datastructures.comparators.HotelReviewComparatorDescending;
import com.hmsproject.datastructures.comparators.HotelStarRatingComparatorAscending;
import com.hmsproject.datastructures.comparators.HotelStarRatingComparatorDescending;
import com.hmsproject.datastructures.enums.HotelSizeEnum;
import com.hmsproject.datastructures.enums.Hotels_DB_enum;
import com.hmsproject.db.HMSDBConnection;
import com.hmsproject.db.HMSDBConnectionFactory;
import com.hmsproject.db.HMSDBType;
import com.hmsproject.db.inmemorydb.DealMap;
import com.hmsproject.search.bean.FilterBean;
import com.hmsproject.search.bean.HotelSorting;
import com.hmsproject.search.bean.PlaceBean;
import com.hmsproject.search.bean.PriceRange;
import com.hmsproject.search.bean.SearchBean;
import com.mongodb.BasicDBObject;

public class HMSExepdiaDBConnection extends HMSDBConnection {
	
	private static HMSExepdiaDBConnection hmsExepdiaDBConnection = new HMSExepdiaDBConnection();
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
	
	public static HMSExepdiaDBConnection getInstance(){
		return hmsExepdiaDBConnection;
	}	

	@SuppressWarnings("deprecation")
	public String executeConnection(String method, String requestParameterString) throws Exception{
		
		String result = "";
		DefaultHttpClient httpclient = new DefaultHttpClient();
		String finalUrl = HMSExpediaDBConstants.getInstance().getBaseUrl(method) + requestParameterString;
		
		System.out.println("EXPEDIA FINAL URL:    " + finalUrl);
		HttpGet httpget = new HttpGet(finalUrl);
		httpget.getRequestLine();
		HttpResponse response = httpclient.execute(httpget);
		HttpEntity entity = response.getEntity();
		if (entity != null) {
			
			InputStream inputStream = null;
			BufferedReader bufferedReader = null;
			
			try{
				inputStream = entity.getContent();
				bufferedReader = new BufferedReader(
		               new InputStreamReader(inputStream));
				
				StringBuilder strBuilder = new StringBuilder();
				
				String line;
				
				while ((line = bufferedReader.readLine()) != null) 
				{
		               strBuilder.append(line);
		        }				
				
				result = strBuilder.toString();
			}finally{
				if(inputStream != null){
					try {
						inputStream.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				
				if(bufferedReader != null){
					try {
						bufferedReader.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				
				httpclient.getConnectionManager().shutdown();	
			}
		}
		
		return result;
	}	
	
	@Override
	public List<Hotel> searchHotels(String hotelIdList)
	{
		
		
		List<Hotel> hotelList = new ArrayList<Hotel>();
		try{
			String searchResult = this.executeConnection("list", "&hotelIdList=" + hotelIdList);
			
			//String searchResult = this.executeConnection("list", "&city=SanFrancisco&arrivalDate=09/04/2015&departureDate=09/05/2015&numberOfResults=10");
			
			//String searchResult = this.executeConnection("list", "&city="+searchBean.getPlaceBean().getPlaceName()+"&arrivalDate=09/04/2015&departureDate=09/05/2015&numberOfResults=10" + filterString);
			hotelList = processSearchResult(searchResult);
		}catch(Exception e){
			e.printStackTrace();
		}

		return hotelList;
	}	
	
	@Override
	public List<Hotel> searchHotels(SearchBean searchBean)
	{
		
		List<Hotel> hotelList = new ArrayList<Hotel>();
		try{
		
			//String searchResult = this.executeConnection("list", "&city=SanFrancisco");
			
			String filterString = processFilterBean(searchBean.getFilterBean());
			//String searchResult = this.executeConnection("list", "&hotelIdList=115718,106066,164153,115993,112932" + filterString);
			String searchResult = this.executeConnection("list", "&city="+searchBean.getPlaceBean().getPlaceName()+"&arrivalDate=09/04/2015&departureDate=09/05/2015&numberOfResults=10" + filterString);

			hotelList = processSearchResult(searchResult);
			setSearchBeanProcessing(searchBean,hotelList);	

			
		}catch(Exception e){
			e.printStackTrace();
		}

		return hotelList;
	}
	
	private List<Hotel> processSearchResult(String searchResult) throws Exception{
		
		
		System.out.println(searchResult);
		
		List<Hotel> hotelList = new ArrayList<Hotel>();
		
		ObjectMapper mapper = new ObjectMapper();
        
        Map<String,Object> map = mapper.readValue(searchResult,new TypeReference<HashMap<String,Object>>(){});
        
        Map<String,Object> hotelListResponseMap = (Map<String,Object>)map.get("HotelListResponse");
        
        Map<String,Object> hotelListMap = (Map<String,Object>)hotelListResponseMap.get("HotelList");
        
        if(hotelListMap == null){
        	return hotelList;
        }
        
        System.out.println(hotelListMap.get("HotelSummary").getClass());
        
        System.out.println("SIZE   " + hotelListMap.get("@size"));
        
        String sizeStr = (String)hotelListMap.get("@size");
        
        List<Map<String,Object>> hotelSummaryList = new ArrayList<Map<String,Object>>();

        if(sizeStr.equals("1")){
        	hotelSummaryList.add((Map<String,Object>)hotelListMap.get("HotelSummary"));
        }else
        {
        	hotelSummaryList = (List<Map<String,Object>>)hotelListMap.get("HotelSummary");
        }
        
        for(int i = 0; i < hotelSummaryList.size();i++){
        	Map<String,Object> hotelSummary = (Map<String,Object>)hotelSummaryList.get(i);
        	
        	Object tripAdvisorRating = hotelSummary.get("tripAdvisorRating");
        	
        	int popularity=1,review=1;
        	
        	if(tripAdvisorRating != null){
        		popularity = (int)Double.parseDouble(tripAdvisorRating.toString());
        	}
        	
        	int distance = 0;
        	
        	if(hotelSummary.get("tripAdvisorReviewCount") != null){
        	 review = (int)Double.parseDouble(hotelSummary.get("tripAdvisorReviewCount").toString());
        	}
        	
        	Hotel hotel = new Hotel(hotelSummary.get("hotelId") + "",(String)hotelSummary.get("name"),(String)hotelSummary.get("city"),(int)(Double.parseDouble(hotelSummary.get("lowRate").toString())),(int)(Double.parseDouble(hotelSummary.get("hotelRating").toString())),null,
					new HotelImage("http://images.travelnow.com"+(String)hotelSummary.get("thumbNailUrl"), null),new StarValue(popularity, distance, review),null);
        	hotelList.add(hotel);
        }
        
        	
		return hotelList;
	}
	
	
	
	private void setSearchBeanProcessing(SearchBean searchBean,List<Hotel> hotelList){
		
		processPlaceBean(searchBean.getPlaceBean(), hotelList);
		processHotelSorting(searchBean.getHotelSorting(), hotelList);		
		
	}
	
	private void processHotelSorting(HotelSorting hotelSorting,List<Hotel> hotelList){
		
		if(hotelSorting == null){
			return;
		}
		
		if(hotelSorting == HotelSorting.NAME_A_TO_Z){
			Collections.sort(hotelList, HotelNameComparatorAscending.getInstance());
		}else
		if(hotelSorting == HotelSorting.PRICE_LOW_TO_HIGH){
			Collections.sort(hotelList, HotelPriceComparatorAscending.getInstance());
		}else
		if(hotelSorting == HotelSorting.PRICE_HIGH_TO_LOW){
			Collections.sort(hotelList, HotelPriceComparatorDescending.getInstance());
		}else
		if(hotelSorting == HotelSorting.STAR_ZERO_TO_FIVE){
			Collections.sort(hotelList, HotelStarRatingComparatorAscending.getInstance());
		}else
		if(hotelSorting == HotelSorting.STAR_FIVE_ZERO){
			Collections.sort(hotelList, HotelStarRatingComparatorDescending.getInstance());
		}else
		if(hotelSorting == HotelSorting.POPULARITY){
			Collections.sort(hotelList, HotelPopularityComparatorDescending.getInstance());
		}else
		if(hotelSorting == HotelSorting.DISTANCE){
			Collections.sort(hotelList, HotelDistanceComparatorDescending.getInstance());
		}else
		if(hotelSorting == HotelSorting.REVIEW_SCORE){
			Collections.sort(hotelList, HotelReviewComparatorDescending.getInstance());
		}
		
		
	}
	
	private String processFilterBean(FilterBean filterBean){
		
		String filterString = "";
		
		if(filterBean == null)
		{
			return filterString;
		}
		
		if(filterBean.getStarRating() != null)
		{
			filterString = HMSExpediaDBConstants.getInstance().getAmbers() + "minStarRating=" + Double.parseDouble(filterBean.getStarRating());
		}
		
		PriceRange priceRange = filterBean.getPriceRange();
		if(priceRange != null){
			filterString += HMSExpediaDBConstants.getInstance().getAmbers() + "minRate=" + filterBean.getPriceRange().getLowerBound();
			filterString += HMSExpediaDBConstants.getInstance().getAmbers() + "maxRate=" + filterBean.getPriceRange().getUpperBound();
		}
		
		return filterString;
	}
	
	private void processPlaceBean(PlaceBean placeBean,List<Hotel> hotelList){

		/*if(placeBean == null){
			return;
		}
		
		if(placeBean.getPlaceName() != null){
			filterquery.append(Hotels_DB_enum.PLACE_NAME.getValue(),placeBean.getPlaceName());
		}*/

	}
	
}
